package com.lktx.sso.system.service;

import cn.hserver.core.ioc.annotation.Autowired;
import cn.hserver.core.ioc.annotation.Bean;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import com.lktx.sso.system.common.MyCode;
import com.lktx.sso.system.dto.PwdDTO;
import com.lktx.sso.system.entity.User;
import com.lktx.sso.system.entity.UserRole;
import com.lktx.sso.system.mapper.RoleMapper;
import com.lktx.sso.system.mapper.UserMapper;
import com.lktx.sso.system.mapper.UserRoleMapper;
import com.lktx.sso.system.utils.AuthUtils;
import com.lktx.sso.system.utils.RsaUtil;

import java.util.*;

import static com.lktx.sso.system.common.MyConstants.*;


/**
 * 用户信息 服务类
 *
*
 * @since 2022-06-12
 */
@Slf4j
@Bean
public class UserService {

    @Autowired
    private UserMapper mapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RoleMapper roleMapper;

    /**
     * 分页查询列表
     *
     * @param page   分页对象
     * @param entity 查询实体
     * @return 所有数据
     */
    public Page<User> page(Page<User> page, User entity) {
        return mapper.paginate(page,
                new QueryWrapper()
                        .like(User::getUsername, entity.getUsername(),!StrUtil.isEmpty(entity.getUsername()))
                        .eq(User::getLocked, entity.getLocked(),entity.getLocked()!=null)
                        .orderBy(User::getUserId,false)
        );
    }

    /**
     * 不分页查询列表
     *
     * @param entity 实体对象
     * @return 查询结果
     */
    public List<User> list(User entity) {
        return mapper.selectListByQuery(new QueryWrapper());
    }

    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     */
    public User getById(Long id) {
        User user = mapper.selectOneById(id);
        if (Objects.nonNull(user)) {
            if (Objects.equals(id, SUPER_ADMIN_ID)) {
                user.setPermissions(Collections.singleton(SUPER_ADMIN_PERM));
            } else {
                user.setPermissions(roleMapper.listPermKey(id));
            }
        }
        AuthUtils.setUser(user);
        return user;
    }

    /**
     * 新增单条数据
     *
     * @param entity 实体对象
     */
    public void save(User entity) {
        long l = mapper.selectCountByQuery(QueryWrapper.create().eq(User::getUsername, entity.getUsername()));
        if (l > 0) {
            throw MyCode.EXIST_ACCOUNT.toException();
        }
        if (StrUtil.hasBlank(entity.getNickname())) {
            entity.setNickname("用户" + RandomUtil.randomString(6));
        }
        if (StrUtil.hasBlank(entity.getPassword())) {
            entity.setPassword(RsaUtil.encrypt(DEFAULT_PASSWORD));
        }
        mapper.insert(entity);
        insertUserRole(entity);
    }

    /**
     * 修改单条数据
     *
     * @param entity 实体对象
     */
    public void update(User entity) {
        if (Objects.equals(entity.getUserId(), SUPER_ADMIN_ID)) {
            throw MyCode.ACCESS_DENIED.toException("超管账号不可编辑");
        }
        if (CollUtil.isNotEmpty(entity.getRoleIds())) {
            userRoleMapper.deleteByQuery(new QueryWrapper().eq(UserRole::getUserId, entity.getUserId()));
            insertUserRole(entity);
        }
        mapper.update(entity);
    }

    /**
     * 批量删除数据
     *
     * @param ids 主键集合
     */
    public void deleteByIds(List<Long> ids) {
        if (ids.contains(SUPER_ADMIN_ID)){
            throw MyCode.ACCESS_DENIED.toException("超管账号不可删除");
        };
        userRoleMapper.deleteByQuery(new QueryWrapper().in(UserRole::getUserId, ids));
        mapper.deleteBatchByIds(ids);
    }

    /**
     * 账号查找
     *
     * @param username 账号
     * @return 账号信息
     */
    public Optional<User> getByUsername(String username) {
        User tabUser = mapper.selectOneByQuery(new QueryWrapper().eq(User::getUsername, username));
        return Optional.ofNullable(tabUser);
    }

    /**
     * 新增角色用户信息
     *
     * @param entity 用户对象
     */
    public void insertUserRole(User entity) {
        // 新增用户与角色管理
        if (CollUtil.isNotEmpty(entity.getRoleIds())) {
            List<UserRole> list = new ArrayList<>();
            for (Long roleId : entity.getRoleIds()) {
                UserRole rm = new UserRole();
                rm.setRoleId(roleId);
                rm.setUserId(entity.getUserId());
                list.add(rm);
            }
            if (!list.isEmpty()) userRoleMapper.batchUserRole(list);
        }
    }

    /**
     * 重置密码
     *
     * @param userId 用户ID
     */
    public void resetPassword(Long userId) {
        if (Objects.equals(userId, SUPER_ADMIN_ID)) throw MyCode.ACCESS_DENIED.toException("超管账号不可编辑");

        long l = mapper.selectCountByQuery(new QueryWrapper().eq(User::getUserId, userId));
        if (l==0) {
            throw MyCode.UNKNOWN_ACCOUNT.toException();
        }
        User user = new User();
        user.setUserId(userId);
        user.setPassword(RsaUtil.encrypt(DEFAULT_PASSWORD));
        mapper.update(user);
    }

    /**
     * 修改密码
     */
    public void changePwd(Long userId, PwdDTO dto) {
        User user = mapper.selectOneById(userId);
        if (Objects.isNull(user)) throw MyCode.UNKNOWN_ACCOUNT.toException();
        if (!RsaUtil.decrypt(user.getPassword()).equals(dto.getPasswordOld())) {
            throw MyCode.DATA_VERIFY_ERROR.toException("旧密码错误");
        }
        User info = new User();
        info.setUserId(userId);
        info.setPassword(RsaUtil.encrypt(dto.getPasswordNew()));
        mapper.update(info);
    }

    /**
     * 修改头像
     */
    public void changeAvatar(Long userId, String avatar) {
        User user = mapper.selectOneById(userId);
        if (Objects.isNull(user)) throw MyCode.UNKNOWN_ACCOUNT.toException();
        User info = new User();
        info.setUserId(userId);
        info.setAvatar(avatar);
        mapper.update(info);
    }

    /**
     * 角色勾选项
     *
     * @param userId 用户ID
     * @return 角色IDs
     */
    public Set<Long> selectRoleIdsByUserId(Long userId) {
        return userRoleMapper.selectRoleIdsByUserId(userId);
    }

}
